<script setup lang="ts">
import { ref, shallowRef, onBeforeMount, nextTick } from 'vue'
import { ElMessage as message } from 'element-plus'
import { listToTree, setTableHeight, sortTreeArr } from '@/common/utils'
import Add from './add.vue'
import Update from './update.vue'
import { primaryColor_hex, primaryColorFade } from '@/theme/config'
import { useResizeLR } from '@/hooks/useResizeLR'
import { useTableMixin } from '@/hooks/useTableMixin'
import { actionKeys } from '@/common/config'
import { getMenuPageApi, getMenuListApi, deleteMenuApi, importMenusApi, getSuccessStatus } from '@/api/menu'

const columns = shallowRef<TableColConfig[]>([
	{
		label: '复选框列',
		prop: 'selection',
		columnKey: 'selection',
		type: 'selection',
		width: 55,
		fixed: 'left',
		align: 'center',
	},
	{
		label: '路由名',
		prop: 'name',
		columnKey: 'name',
		width: 120,
		align: 'center',
	},
	{
		label: '组件路径',
		prop: 'component',
		columnKey: 'component',
		width: 150,
		showOverflowTooltip: true,
	},
	{
		label: 'meta',
		prop: 'meta',
		columnKey: 'meta',
		childrenCols: [
			{
				label: '页面标题',
				prop: 'title',
				columnKey: 'title',
				width: 150,
				align: 'center',
			},
			{
				label: '菜单图标',
				prop: 'icon',
				columnKey: 'icon',
				width: 150,
				align: 'center',
			},
			{
				label: '菜单的排序序号',
				prop: 'sortValue',
				columnKey: 'sortValue',
				width: 150,
				align: 'center',
			},
			{
				label: '是否缓存',
				prop: 'noKeepAlive',
				columnKey: 'noKeepAlive',
				width: 100,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.noKeepAlive ? '否' : '是'
				},
			},
			{
				label: '是否存在菜单中',
				prop: 'noInMenu',
				columnKey: 'noInMenu',
				width: 120,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.noInMenu ? '否' : '是'
				},
			},
			{
				label: '是否隐藏菜单',
				prop: 'hiddenMenu',
				columnKey: 'hiddenMenu',
				width: 100,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.hiddenMenu ? '是' : '否'
				},
			},
			{
				label: '是否隐藏布局',
				prop: 'hiddenLayout',
				columnKey: 'hiddenLayout',
				width: 100,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.hiddenLayout ? '是' : '否'
				},
			},
			{
				label: '是否固定tab页',
				prop: 'affix',
				columnKey: 'affix',
				width: 120,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.affix ? '是' : '否'
				},
			},
			{
				label: '是否跳往外部链接',
				prop: 'link',
				columnKey: 'link',
				width: 135,
				align: 'center',
				contentRender: ({ row, column: _column }) => {
					return row.link ? '是' : '否'
				},
			},
		],
	},
	{
		label: '操作',
		prop: 'operation',
		columnKey: 'operation',
		fixed: 'right',
		align: 'center',
		resizable: false,
		// width: 128,
	},
])
const treeHeight = ref<number>()
const treeData = ref<MenuType[]>([])
const expandedKeys = ref<IdType[]>([])
const selectedKey = ref<IdType>()
const hasChildKeys = ref<Set<IdType>>(new Set([]))
const selectedNode = ref({} as MenuType)
const searchOptions = ref<SearchOptionType[]>([
	{ type: 'input', id: 'name', props: { label: '路由名' } },
	{ type: 'input', id: 'component', props: { label: '组件路径' } },
	{ type: 'input', id: 'label', props: { label: '路由标题' } },
	{
		type: 'select',
		id: 'onInMenu',
		props: { label: '是否存在在菜单' },
		innerComponentProps: {
			clearable: true,
			filterable: true,
			options: [
				{ label: '是', value: 0, disabled: false },
				{ label: '否', value: 1, disabled: false },
			],
		},
	},
	{
		type: 'select',
		id: 'noKeepAlive',
		props: { label: '是否缓存' },
		innerComponentProps: {
			clearable: true,
			filterable: true,
			options: [
				{ label: '是', value: 0, disabled: false },
				{ label: '否', value: 1, disabled: false },
			],
		},
	},
])

useResizeLR({
	containerSelector: '.routeManage .container',
	leftBoxSelector: '.routeManage .container .left',
	moveBarSelector: '.routeManage .container .bar',
	rightBoxSelector: '.routeManage .container .right',
	//  lMinW:180,
	rMinW: 800,
	innerMarginW: 10,
})

const {
	basicPaginationConfig, // 表格分页基础配置
	tableRef, // 表格ref
	current, // 当前页码
	size, // 页尺寸
	total, // 总条数
	addRef, // 新增组件ref
	updateRef, // 更新组件ref
	detailRef, // 详情组件ref
	filterOptions, // 查询条件
	getData, // 获取页数据的方法
	tableHeight, // 表格高度
	addDialogVisible, //新增对话框显示隐藏状态
	updateDialogVisible, //更新对话框显示隐藏状态
	tableList, // 表格数据
	selectedRows, // 选中行数据
	editRow, // 当前编辑数据
	addDialogIsFull, // 新增对话框是否全屏的状态
	updateDialogIsFull, // 更新对话框是否全屏的状态
	detailDialogIsFull, // 详情对话框是否全屏的状态
	fixedColWidth, // 固定列列宽
	handleSearchPanelcollapsed, //search-panel组件的 @collapsed 的处理函数
	handleSearch, // 搜索处理函数
	handleReset, // 重置表格数据处理函数
	handlePaginationChange, // 处理分页器变化处理函数
	handleColumnsChange, // 表头变化组件的处理函数
	handleAdd, // 点击新增按钮回调
	handleUpdate, // 点击更新按钮回调
	handleDelete, // 删除处理函数
	handleSelectedRowChange, // 表格选中行变化的回调
	handleImport, // 导入表格处理函数
	handleExport, // 导出表格数据处理函数
	handleAddCommit, // 新增提交处理函数
	handleUpdateCommit, // 更新提交处理函数
} = useTableMixin<MenuType>({
	columns,
	listApiFunc: getMenuPageApi,
	deleteApiFunc: deleteMenuApi,
	importApiFunc: importMenusApi,
	actionList: [actionKeys.update, actionKeys.delete],
	searchPanelcollapsed_after: (h) => {
		setTableHeight({
			tableHeightRef: treeHeight,
			otherSectionHeight: 52 + h,
			isTable: false,
		})
	},
	add_before: () => {
		if (!selectedKey.value) {
			message.warning('请先在左侧树选择父节点')
			return
		}
		if (selectedNode.value.component) {
			message.warning('选中的是叶子节点，不可添加子路由')
			return
		}
		if (selectedNode.value.link) {
			message.warning('选中的是外部链接，不可添加子路由')
			return
		}
		return true
	},
	update_before: () => {
		return true
	},
	delete_before: () => {
		return true
	},
	add_after: () => {
		getTreeData()
	},
	delete_after: () => {
		if (editRow.value.name == selectedNode.value.name) {
			selectedNode.value = {} as MenuType
			selectedKey.value = ''
		}
		getTreeData()
	},
	query_after: () => {},
	update_after: () => {
		getTreeData()
	},
	search_after: () => {},
	reset_after: () => {
		selectedNode.value = {} as MenuType
		selectedKey.value = ''
	},
})

onBeforeMount(() => {
	getTreeData()
})

// 页面内函数统一使用function，箭头函数不能提升，书写顺序上有一定局限性

async function getTreeData() {
	const res = await getMenuListApi({ status: 1 })
	if (res.code == getSuccessStatus()) {
		const tree = listToTree<MenuType>(
			res.data,
			'id',
			'parentId',
			'children',
			false,
			(i) => {
				if (i.component || i.link) i.style = { color: primaryColor_hex }
			},
			(j) => {
				hasChildKeys.value.add(j.name)
			}
		)

		treeData.value = sortTreeArr<MenuType>([tree], 'sortValue')
		nextTick(() => {
			expandedKeys.value = [...hasChildKeys.value]
		})
		// console.log([...hasChildKeys.value])
		// console.log(tree)
	}
}

function handleSelectTreeNode(node: MenuType) {
	if (node.name == selectedKey.value) {
		selectedNode.value = {} as MenuType
		selectedKey.value = ''
		handleReset()
	} else {
		selectedNode.value = node
		selectedKey.value = node.name
		handleSearch({ name: selectedNode.value.name })
	}
}

function customNodeClass(data: MenuType, node: Node) {
	if (data.component || data.link) {
		return 'leafTextColor'
	}
	return null
}

function nodeContentRender(h: any, e: any) {
	// console.log(h,e)
	//console.log(e)
	if (selectedKey.value == e.data.name) return h('span', { style: { backgroundColor: primaryColorFade(0.5) } }, e.data.title)
	else return e.data.title
}
</script>

<template>
	<div class="routeManage">
		<search-panel @collapsed="handleSearchPanelcollapsed" @search="handleSearch" @reset="handleReset" :options="searchOptions" />
		<div class="container" style="display: flex">
			<div class="left" :style="{ height: treeHeight + 'px' }">
				<el-scrollbar>
					<el-tree
						:render-content="nodeContentRender"
						:expand-on-click-node="false"
						:props="{ children: 'children', label: 'title', class: customNodeClass }"
						node-key="name"
						:data="treeData"
						:default-expanded-keys="expandedKeys"
						@node-click="handleSelectTreeNode"
					/>
				</el-scrollbar>
			</div>
			<div class="bar" :style="{ height: treeHeight + 'px' }"></div>
			<div class="right">
				<div class="my-table-tool">
					<div class="tool-left">
						<el-upload :http-request="handleImport" v-if="$hasAuth([actionKeys.import])" accept=".xls,.xlsx" :show-file-list="false">
							<el-button type="primary" style="margin-right: 5px">导入菜单</el-button>
						</el-upload>
						<el-button type="primary" style="margin-right: 5px" @click="handleExport" v-if="$hasAuth([actionKeys.export])">导出excel</el-button>
					</div>
					<div class="tool-right">
						<el-button type="primary" style="margin-right: 5px" @click="handleAdd" v-if="$hasAuth([actionKeys.add])">新增子路由</el-button>
						<set-table-columns :list="columns" @confirm="handleColumnsChange" />
					</div>
				</div>

				<!-- 'max-content':保证每一列完整显示 -->
				<my-table
					ref="tableRef"
					border
					stripe
					:data="tableList"
					:columns="columns"
					style="width: 100%"
					class="myTable"
					rowKey="id"
					:maxHeight="tableHeight"
					@selection-change="handleSelectedRowChange"
					:pagination="{ ...basicPaginationConfig, current, size, total }"
				> 
					<template #operation="{ row }">
						<el-button type="primary" size="small" v-if="$hasAuth([actionKeys.update])" @click="handleUpdate(row)">修改</el-button>

						<el-popconfirm
							title="确定要删除吗?"
							confirm-button-text="确定"
							cancel-button-text="取消"
							@confirm="handleDelete(row)"
							v-if="$hasAuth([actionKeys.delete])"
							:disabled="[...hasChildKeys].includes(row.name)"
						>
							<template #reference><el-button type="danger" size="small" :disabled="[...hasChildKeys].includes(row.name)">删除</el-button></template>
						</el-popconfirm>
					</template>
				</my-table>
			</div>
		</div>

		<el-dialog v-model="addDialogVisible" title="新增子路由" width="80%" :modal="false" draggable :close-on-click-modal="false" align-center :fullscreen="addDialogIsFull">
			<el-scrollbar :maxHeight="addDialogIsFull ? 0 : $getDialogBodyMaxHeight()">
				<!--  套个div防止无论何时都出现横向滚动 -->
				<div style="padding: 0 10px">
					<Add :parentNode="(selectedNode as any)" ref="addRef" />
				</div>
			</el-scrollbar>
			<template #footer>
				<div class="dialog-footer" style="display: flex; justify-content: flex-end">
					<screen-full-toggle-icon @toggle="(v:boolean)=>{addDialogIsFull=v}" />
					<el-button @click="addDialogVisible = false">取消</el-button>
					<el-button type="primary" @click="handleAddCommit">确定</el-button>
				</div>
			</template>
		</el-dialog>

		<el-dialog v-model="updateDialogVisible" title="更新子路由" width="80%" :modal="false" draggable :close-on-click-modal="false" align-center :fullscreen="updateDialogIsFull">
			<el-scrollbar :maxHeight="updateDialogIsFull ? 0 : $getDialogBodyMaxHeight()">
				<div style="padding: 0 10px">
					<Update :editRow="editRow" ref="updateRef" />
				</div>
			</el-scrollbar>
			<template #footer>
				<div class="dialog-footer" style="display: flex; justify-content: flex-end">
					<screen-full-toggle-icon @toggle="(v:boolean)=>{updateDialogIsFull=v}" />
					<el-button @click="updateDialogVisible = false">取消</el-button>
					<el-button type="primary" @click="handleUpdateCommit">确定</el-button>
				</div>
			</template>
		</el-dialog>
	</div>
</template>

<style scoped lang="scss">
.routeManage {
	.container {
		.left {
			overflow: hidden auto;
			margin-top: 52px;
			background-color: white;
			width: 180px;
			flex-shrink: 0;
		}
		.bar {
			width: 5px;
			//background-color: gainsboro;
			margin: 52px 0 0 10px;
			background-clip: content-box;
			padding: 0 2px;
			flex-shrink: 0;
		}
		.bar:hover {
			background-color: gainsboro;
		}
		.right {
			padding-left: 20px;
			width: calc(100% - 180px - 15px);
		}
	}

	:deep(.el-table thead .el-table__cell) {
		text-align: center;
		// background-color: rgb(232, 246, 241) !important;
	}
}
</style>
